#pragma once
//#include "common/types.h"

#include <vector>
#include <string>

#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/device/back_inserter.hpp>

#pragma warning(push)
#pragma warning(disable:4310)//cast truncates constant value
#pragma warning(disable:4244)//conversion from std::streamsize to size_t
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#pragma warning(pop)

#include <sstream>

namespace tools
{
    namespace detail
    {
        typedef ::std::vector<char>           Blob;
        typedef ::std::string                 String;
    }

    template<class T> void SerializeBinary(const T& val, detail::Blob& dest)
    {
        boost::iostreams::stream<boost::iostreams::back_insert_device<detail::Blob>> os(dest);
        boost::archive::binary_oarchive oa(os, boost::archive::archive_flags::no_header);
        oa << val;
        os.flush();
    }

    template<class T> void DeserializeBinary(const detail::Blob& source, T& dest)
    {
        boost::iostreams::basic_array_source<char> buffer(&source[0], source.size());
        boost::iostreams::stream<decltype(buffer)> is(buffer); 
        boost::archive::binary_iarchive ia(is, boost::archive::archive_flags::no_header);
        ia >> dest;
    }

    template<class T> void SerializeText(const T& val, detail::String& dest)
    {
        std::stringstream stream;
        boost::archive::text_oarchive arch(stream);
        arch << val;
        dest = stream.str();
    }

    template<class T> void DeserializeText(const detail::String& source, T& dest)
    {
        std::stringstream stream;
        stream << source;
        boost::archive::text_iarchive arch(stream);
        arch >> dest;
    }

    template<class T> void SerializeXml(const T& val, detail::String& dest)
    {
        std::stringstream stream;
        boost::archive::xml_oarchive arch(stream);
        arch << boost::serialization::make_nvp("object", val);
        dest = stream.str();
    }

    template<class T>  void DeserializeXml(const detail::String& source, T& dest)
    {
        std::stringstream stream;
        stream << source;
        boost::archive::xml_iarchive arch(stream);
        arch >> boost::serialization::make_nvp("object", dest);
    }

}//namespace tools
